// arp.c
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>


#include "ethqos.h"
#include "evalsoc.h"
#include "arp.h"
#include "evalsoc_uart.h"
#include "dbg_cli.h"
#include "ipaddr.h"



#pragma pack(push, 1)
typedef struct {
    uint8_t dest_mac[6];
    uint8_t src_mac[6];
    uint16_t ethertype;
} EthernetHeader;

typedef struct {
    uint16_t hw_type;    // 硬件类型
    uint16_t proto_type; // 协议类型
    uint8_t hw_len;      // 硬件地址长度
    uint8_t proto_len;   // 协议地址长度
    uint16_t opcode;     // 操作码
    uint8_t sender_mac[6]; // 发送方MAC地址
    uint8_t sender_ip[4];  // 发送方IP地址
    uint8_t target_mac[6]; // 目标方MAC地址
    uint8_t target_ip[4];  // 目标方IP地址
} ARPHeader;



#pragma pack(pop)




/**
 * @brief 回应arp请求
 * @param pctx 数据包的描述符结构体
 * @param pdat 数据包
 * @param tlen 数据包长度
 * @return 0 成功, 其他失败
 */
int arp_make_reply(eqos_context_t *pctx,uint8_t *pdat,int tlen){

	EthernetHeader *eth = (EthernetHeader*)pdat;
    ARPHeader *arp = (ARPHeader*)(pdat + sizeof(EthernetHeader));
    
    memcpy(eth->dest_mac, arp->sender_mac, 6);
    memcpy(eth->src_mac, DEV_MAC, 6);

    arp->opcode = htons(2); // ARP响应
    memcpy(arp->target_mac, arp->sender_mac, 6);
    memcpy(arp->target_ip, arp->sender_ip, 4);
    memcpy(arp->sender_mac, DEV_MAC, 6);
    memcpy(arp->sender_ip, DEV_IP, 4);
    
	int iret = dbg_eth_trans( pctx, pdat, (int)tlen );
    if (iret!= 0) {
        printf("dbg_eth_trans failed\n");
        return -1;
    }
	return 0;
}


/**
 * @brief 发送arp请求
 * @param pctx   数据包的描述符结构体
 * @param target_ip 目标IP地址
 * @return 0 成功, 其他失败
 */
int arp_make_request(eqos_context_t *pctx, uint8_t *target_ip) {
    // 定义ARP结构体
    ARPHeader arp;
    // 定义以太网头
    EthernetHeader eth;

    // 填充以太网头
    memset(eth.dest_mac, 0xFF, 6); // 目的MAC地址为广播地址
    memcpy(eth.src_mac, DEV_MAC, 6); // 源MAC地址为设备MAC地址
    eth.ethertype = htons(0x0806); // ARP协议类型

    // 填充ARP头
    arp.hw_type = htons(1); // 硬件类型为以太网
    arp.proto_type = htons(0x0800); // 协议类型为IPv4
    arp.hw_len = 6; // 硬件地址长度为6字节
    arp.proto_len = 4; // 协议地址长度为4字节
    arp.opcode = htons(1); // ARP请求
    memcpy(arp.sender_mac, DEV_MAC, 6); // 发送方MAC地址为设备MAC地址
    memcpy(arp.sender_ip, DEV_IP, 4); // 发送方IP地址为设备IP地址
    memset(arp.target_mac, 0x00, 6); // 目标MAC地址为0，
    memcpy(arp.target_ip, target_ip, 4); // 目标IP地址为我们要请求的IP地址

    // 将以太网头和ARP头复制到数据包中
    uint8_t *pdat = malloc(sizeof(EthernetHeader) + sizeof(ARPHeader));
    if (pdat == NULL) {
        printf("malloc failed\n");
        return -1;
    }

    memcpy(pdat, &eth, sizeof(EthernetHeader));
    memcpy(pdat + sizeof(EthernetHeader), &arp, sizeof(ARPHeader));

    // 发送ARP请求
    int tlen = sizeof(EthernetHeader) + sizeof(ARPHeader);
    int iret = dbg_eth_trans(pctx, pdat, tlen);
    if (iret!= 0) {
        printf("dbg_eth_trans failed\n");
        return -1;
    }

    // 释放分配的内存
    fpa_free(pdat);

    return 0;
}


